package com.hongfan.common.utils.encrypt;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.StrUtil;
import java.nio.charset.StandardCharsets;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SM4加解密辅助方法
 *
 * @author yjr
 */
@SuppressWarnings("all")
public class SM4Utils {

    public String secretKey = "(B212&*)!cb124-d";
    public String iv = "d-421bc!)*&212B(";
    public boolean hexString = false;

    /**
     * 编码
     */
    private String charset = StandardCharsets.UTF_8.name();

    private final Pattern pattern = Pattern.compile("\\s*|\t|\r|\n");

    public SM4Utils() {

    }

    public SM4Utils(String charset) {
        this.charset = charset;
    }

    public String encryptDataECB(String plainText) {
        if (plainText == null || plainText.isEmpty()) {
            return plainText;
        }
        try {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_ENCRYPT;
            byte[] keyBytes;
            if (hexString) {
                keyBytes = hexStringToBytes(secretKey);
            } else {
                keyBytes = secretKey.getBytes();
            }
            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_ecb(ctx, plainText.getBytes(charset));
            String cipherText = Base64.encode(encrypted);
            if (cipherText != null && cipherText.trim().length() > 0) {
                Matcher m = pattern.matcher(cipherText);
                cipherText = m.replaceAll("");
            }
            return cipherText;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public String decryptDataECB(String cipherText) {
        if (cipherText == null || cipherText.isEmpty()) {
            return cipherText;
        }
        try {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            if (hexString) {
                keyBytes = hexStringToBytes(secretKey);
            } else {
                keyBytes = secretKey.getBytes();
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);
            byte[] input = Base64.decode(StrUtil.bytes(cipherText, charset));
            byte[] decrypted = sm4.sm4_crypt_ecb(ctx, input);
            return new String(decrypted, charset);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public String encryptDataCBC(String plainText) {
        if (plainText == null || plainText.isEmpty()) {
            return plainText;
        }
        try {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_ENCRYPT;

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString) {
                keyBytes = hexStringToBytes(secretKey);
                ivBytes = hexStringToBytes(iv);
            } else {
                keyBytes = secretKey.getBytes();
                ivBytes = iv.getBytes();
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_enc(ctx, keyBytes);
            byte[] encrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, plainText.getBytes(charset));
            String cipherText = Base64.encode(encrypted);
            if (cipherText != null && cipherText.trim().length() > 0) {
                Matcher m = pattern.matcher(cipherText);
                cipherText = m.replaceAll("");
            }
            return cipherText;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public String decryptDataCBC(String cipherText) {
        if (cipherText == null || cipherText.isEmpty()) {
            return cipherText;
        }
        try {
            SM4Context ctx = new SM4Context();
            ctx.isPadding = true;
            ctx.mode = SM4.SM4_DECRYPT;

            byte[] keyBytes;
            byte[] ivBytes;
            if (hexString) {
                keyBytes = hexStringToBytes(secretKey);
                ivBytes = hexStringToBytes(iv);
            } else {
                keyBytes = secretKey.getBytes();
                ivBytes = iv.getBytes();
            }

            SM4 sm4 = new SM4();
            sm4.sm4_setkey_dec(ctx, keyBytes);

            byte[] input = Base64.decode(StrUtil.bytes(cipherText, charset));
            byte[] decrypted = sm4.sm4_crypt_cbc(ctx, ivBytes, input);
            return new String(decrypted, charset);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * Convert hex string to byte[]
     *
     * @param hexString the hex string
     * @return byte[]
     */
    private byte[] hexStringToBytes(String hexString) {
        if (hexString == null || "".equals(hexString)) {
            return null;
        }

        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    /**
     * Convert char to byte
     *
     * @param c char
     * @return byte
     */
    private byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }














}